/*
	Filename	:	bjRules.h
	Author(s)	:	Ray E. Bornert II
	Date		:	2002-MAR-26
	Copyright	:	(c) 2002 RealTimeGaming

	History		:
*/

//////////
// GATE //
//////////
#ifndef _BJRULES_H_
#define _BJRULES_H_

/////////////
// FORWARD //
/////////////
class BJRules;
class ODBCQuery;

/////////////
// DEFINES //
/////////////
enum	GameSidebet	{ Insure, MAXSIDEBET };

#define OPTION_FLAG(c)		(1<<(c))
//#define MAXSPLITRULES		(8)

//////////////
// INCLUDES //
//////////////
#include "lib.h"
#include "bjhand.h"
#include "bjbonus.h"
#include "bjaction.h"

////////////
// OBJECT //
////////////
class BJRules
{
/////////////
// MEMBERS //
/////////////

private://MEMBERS

	//one ruleset defined for each possible ruleSetId
	//ruleSetId value 255 (0xff) is reserved and should not be used
	static	BJRules*	m_pRuleSet[ 256 /*index by ruleSetId*/];


	//card values
	static int		m_cardValue[64];

	//a unique id for this specific rule set
	int		m_ruleSetId;

	uint8	m_nBJBets;			//max number of bets/hands (bets player can place)
	int		m_nDecks;			//number of decks to use in the shoe

	//64bits,  1 per card,  0=present, 1=removed
	__int64	m_deckFilter;

	//basic flags
	int		m_maximumHands;		//should always be 3

	//forces aces to always be valued at exactly 1 and only 1
	int		m_isHardAces;		//should normally be false

	//bust totals
	int		m_playerBustTotal;	//should always be 22
	int		m_dealerBustTotal;	//should always be 22

	/// [2013-07-16] Charles. Added for supporting 'Zappit Rackcard'.
	// dealer push value
	int		m_dealerPushTotal;	// 22 only if Zappit, otherwise 0.

	//bet/payout percentages
	float	m_payoutWin;		//units to add to a normal win	typically  1.0
	float	m_payoutLoss;		//units to add to a normal loss typically -1.0
	float	m_payoutTie;		//units to add to a normal tie	typically  0.0

	//sidebet/payout percentages
	float	m_insureBet;		//percentage of original bet
	float	m_insurePayout;		//units to add to a winning insure bet

	//surrender payout
	float	m_surrenderPayout;	//units to subtract from current bet

	//character script for the deal
	char	m_dealScript[8];
	int		m_dealScriptLen;

	//some actions prevent others from occuring
	int		m_preclusion[ MAXACTION ][ MAXACTION ];

	//action table
	int		m_nActionRules;

#define MAXACTIONRULES (256)
	BJAction	m_actionRules[ MAXACTIONRULES ];

	//bonus table
	int		m_nBonusRules;

#define MAXBONUSRULES (256)
	BJBonus	m_bonusRules[ MAXBONUSRULES ];

public:	//MEMBERS

/////////////
// METHODS //
/////////////

private://METHODS

	//STATIC
//	static void LoadRuleSet( uint8 ruleSetId );
//	static void LoadRuleSetId( uint8 machid, uint8* ruleSetId );

	//
	int CanDealer			( GameAction action, BJHand* pHand, int nHands );
	int CanPlayer			( GameAction action, BJHand* pHand, int nHands );
	int GetHandTotal		( BJHand* pHand, int* isSoft=0 );
	int IsSignaledAction	( BJHand* pHand, GameAction action );
	int IsPrecluded			( BJHand* pHand, GameAction action );

	//INIT ROUTINES
	void InitRules_Common();
	void InitRules_StandardBlackjack();
	void InitRules_Pontoon();
	void InitRules_DoubleExposure21();
	void InitRules_Caribbean21();
	void InitRules_Super21();
	void InitRules_Spanish21();
	void InitRules_PerfectPairs();

	/// [2013-07-09] Charles, Added for supporting 'Zappit Rackcard'.
	void InitRules_Zappit();
	
	void AddRuleAction
	(
		char		who,
		GameAction	action,
		int			minHands,
		int			maxHands,
		int			minCards,
		int			maxCards,
		int			minTotal,
		int			maxTotal,
		int			minSoft,
		int			maxSoft,
		char*		pPattern2,
		char*		pPattern //21 cards
	);

	void AddRuleBonus
	(
		char	who,			//dealer or player
		char	type,			//win or instant
		char*	pName,			//name of the bonus
		char*	pPattern,		//card pattern
		int		minHands,		//min hands to qualify
		int		maxHands,		//max hands to qualify
		int		minCards,		//min cards to qualify
		int		maxCards,		//max cards to qualify
		int		minTotal,		//min total to qualify
		int		maxTotal,		//max total to qualify
		int		minNBets,		//min number of bets
		int		maxNBets,		//max number of bets
		int		bonusTotal,		//bonus added to hand score
		float	bonusPayout,	//bonus payout in terms of the original bet
		char*	pPattern2=NULL	//card pattern2
	);

	int	IsStandardDeal();
	int GetPositionDUC();

	//bonus routines
	BJBonus* GetPlayerWinBonus( BJHand* pPlayer, int nHands, BJHand* pDealer );
	BJBonus* GetDealerWinBonus( BJHand* pDealer, int nHands );

	BJBonus* GetDealerWinBonusPossible( BJHand* pHand, int nHands );

public:	//METHODS

	//STATIC

	//RULE SET
	static BJRules* GetRuleSet( uint8 ruleSetId);
	static void SetRuleSet( uint8 ruleSetId, BJRules* pRules );
	static void NewRuleSet( uint8 ruleSetId, BJRules* pRules );

	//CARD ROUTINES
	static int CardCode( int index );
	static int CardCode( int rank, int suit );
	static int CardSuit( int card );
	static int CardRank( int card );
	static int CardIndex( int card );
	static int CardValue( int card );
	static int CardRankValue( unsigned char rank );

	//CONSTRUCTORS
	BJRules();
	BJRules( int ruleSetId );
	BJRules( BJRules* pRules );

	//PLAYER
	int GetPlayerOptions	( BJHand* pHand, int nHands, BJHand* pDealer );

	int CanPlayerBet		( BJHand* pHand, int nHands );
	int CanPlayerHit		( BJHand* pHand, int nHands );
	int CanPlayerStand		( BJHand* pHand, int nHands );
	int	CanPlayerSplit		( BJHand* pHand, int nHands );
	int CanPlayerDouble		( BJHand* pHand, int nHands );
	int CanPlayerSurrender	( BJHand* pHand, int nHands );
	/// [2013-07-09] Charles. Added for supporting 'Zappit Rackcard'.
	int CanPlayerZap		( BJHand* pHand, int nHands  );

	int CanPlayerInsure		( BJHand* pDealer );


	void KeepThePlayerSafe( BJHand* pPlayer, int nHands, BJHand* pDealer, int* pOptions );

	//DEALER
	int GetDealerOptions	( BJHand* pHand, int nHands );
	int CanDealerHit		( BJHand* pHand, int nHands );
	int CanDealerStand		( BJHand* pHand, int nHands );

	//PAYOUT LOGIC
	int GetPayout
	(
		int bet,
		BJHand* pPlayer,
		BJHand* pDealer,
		int nHands,
		char** ppPlayerBonusName,
		char** ppDealerBonusName
	);
	int GetPayout( GameSidebet sidebet, int bet, BJHand* pPlayer, BJHand* pDealer );
	int CanPayout( int bet, BJHand* pDealer );

	//DEAL SCRIPT
	void GetDealScript( char** ppScript, int* pDealScriptLen );

	//NEED TO KNOW
	int EndOfTurnPlayer( BJHand* pPlayer, BJHand* pDealer, int nHands );
	int EndOfTurnDealer( BJHand* pDealer );
	int IsPlayerHandBusted( BJHand* pPlayer );
	int IsPlayerHandAlive( BJHand* pPlayer );
	int	IsSoftAces();
	int	IsHardAces();    

	__int64 GetDeckFilter();

	void SetDealScript( char* pScript );

	int	ImportFromQuery( ODBCQuery* query, int ruleSetId );
	int	ImportFromQueryAction( ODBCQuery* query );
	int	ImportFromQueryBonus( ODBCQuery* query );

	void SetPreclusions( GameAction action, char* actionString );
	void SetPreclusions( char* actionString, GameAction action );
	void SetDeckFilter( char* filterString );
	void SetDeckFilterBit( int cardIndex );

	void AddRuleAction( BJAction* pAction );
	void AddRuleBonus( BJBonus* pBonus );

	int ValidateImport( BJRules* master );

	int	GetNDecks() { return m_nDecks; };
	void SetNDecks( uint8 nDecks ) { m_nDecks = nDecks; };
	void SetMaxBJBets( uint8 nBets ) 
	{ 
		m_nBJBets = nBets; 
	}

	uint8 GetMaxBJBets() 
	{ 
		return m_nBJBets; 
	}

    // kharmon.  06-28-06.  Need to know what percent of the original bet to charge for insurance bet.
    float getInsuranceCostPercentage() 
    {
        return m_insureBet;
    }

	int GetActionsOffered();
	int IsOffered( GameAction action );
};
#endif
